﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ZDT.Task.Job;
using ZDT.Task.Entity;
using ZDT.Task.Plan;
using ZDT.Task.Data;
using ZDT.Http;
using ZDT.Text;
using ZDT.Common;

namespace ZDT.Task.TGather
{
    public class GatherJob : TaskItemJob<GatherInfo,GatherResult>
    {
        public GatherJob(PlanItem<GatherInfo> planItem, GatherResult result)
            : base(planItem, result)
        {
        }
        protected override void Init()
        {
            InitParam();
            base.Init();
            Login();
            Result.LastPageIndex = Setting.ListPageInfo.Index;
            Result.PageCount = GetPageCount(Setting.BaseUrl, "");
            for (int k = Result.LastPageIndex; k <= Result.PageCount; k++)
            {
                //GetPageList(k);
                var workItem = new WorkItem<GatherInfo>();
                workItem.Index = k;
                workItem.Params.Add(k);
                workItem.Params.Add(Result.PageCount);
                workItem.Type = WorkItemType.GetList;
                AddWorkItem(workItem);
            }
        }
        protected override void ExecuteOne(object param)
        {
            base.ExecuteOne(param);
            var workItem = param as WorkItem<GatherInfo>;
            switch (workItem.Type)
            {
                case WorkItemType.Login:
                    Login();
                    break;
                case WorkItemType.GetList:
                    GetPageList(workItem.Index);
                    break;
                case WorkItemType.GetData:
                    GetDetail(workItem.Params[0].ToString());
                    break;
                case WorkItemType.DownFile:
                    string fileName=workItem.Params[0].ToString();
                    string newFileName = Utility.NewImageFilePath(System.IO.Path.GetExtension(fileName));
                    DownloadFile(fileName,newFileName);
                    break;
                case WorkItemType.Pulish:
                    break;
                case WorkItemType.Refresh:
                    break;
                case WorkItemType.Other:
                    break;
                default:
                    break;
            }
        }
        private void InitParam()
        {
            if (string.IsNullOrEmpty(Setting.RootUrl))
            {
                var m = StringMatch.RHttpRoot.Match(Setting.BaseUrl);
                if (m != null)
                {
                    Setting.RootUrl = m.Value;
                }
            }
        }
        private void Login()
        {
            if (Setting.LoginInfo != null)
            {
                if (!string.IsNullOrEmpty(Setting.LoginInfo.Url))
                {
                    string html = Url.GetSource(Setting.LoginInfo.Url, Setting.Encode, Setting.LoginInfo.Cookie, p =>
                    {
                        Setting.LastCookie = p.CookieContainer.GetCookieHeader(p.RequestUri);
                    });
                }
                else if (!string.IsNullOrEmpty(Setting.LoginInfo.Cookie))
                {
                    Setting.LastCookie = Setting.LoginInfo.Cookie;
                }
            }
        }
        private int GetPageCount(string url, string pageCountPattern)
        {
            int result = 0;
            string html = Url.GetSource(url, Setting.Encode, Setting.LastCookie);
            int.TryParse(StringMatch.Match(html, pageCountPattern), out result);
            return result;
        }
        private List<ListItemInfo> GetPageList(int pageIndex)
        {
            string html = Url.GetSource(Setting.ListPageInfo.ListUrl, Setting.Encode, Setting.LastCookie);
            var result = new List<ListItemInfo>();
            if (Setting.ListPageInfo.DetailRule == null)
            {
                var itemUrls = TFilters(html, Setting.ListPageInfo.UrlRule);
                foreach (var item in itemUrls)
                {
                    if (!string.IsNullOrEmpty(item))
                    {
                        var itemInfo = new ListItemInfo();
                        itemInfo.Url = AttachRoot(item);
                        itemInfo.Caption = item;
                        result.Add(itemInfo);
                    }
                }
                var itemCaps = TFilters(html, Setting.ListPageInfo.CapRule);
                int k = 0;
                foreach (var item in itemCaps)
                {
                    if (!string.IsNullOrEmpty(item))
                    {
                        if (result.Count > k)
                        {
                            result[k].Caption = item;
                        }
                        k++;
                    }
                }
            }
            else
            {
                if (Setting.ListPageInfo.UrlRule == null || Setting.ListPageInfo.UrlRule == null)
                {
                    var items = TFilters(html, Setting.ListPageInfo.DetailRule, new List<string>() {"url","cap" });
                    foreach (var item in items)
                    {
                        var itemInfo = new ListItemInfo();
                        string url = item["url"];
                        string cap = item["cap"];
                        itemInfo.Url = AttachRoot(url);
                        itemInfo.Caption = cap;
                        result.Add(itemInfo);
                    }
                }
                else
                {
                    var items = TFilters(html, Setting.ListPageInfo.DetailRule);
                    foreach (var item in items)
                    {
                        if (!string.IsNullOrEmpty(item))
                        {
                            var itemInfo = new ListItemInfo();
                            string url = TFilter(item, Setting.ListPageInfo.UrlRule);
                            string cap = TFilter(item, Setting.ListPageInfo.CapRule);
                            itemInfo.Url = AttachRoot(url);
                            itemInfo.Caption = cap;
                            result.Add(itemInfo);
                        }
                    }
                }
            }
            if (result.Count > 0)
            {
                for (int k = 0; k < result.Count; k++)
                {
                    var workItem = new WorkItem<GatherInfo>();
                    workItem.Index = k;
                    workItem.Params.Add(result[k]);
                    workItem.Type = WorkItemType.GetData;
                    AddWorkItem(workItem);
                }
            }
            return result;
        }
        private DetailItemInfo GetDetail(string url)
        {
            DetailItemInfo result = new DetailItemInfo();
            result.Url=url;
            string html = Url.GetSource(url,Setting.Encode,Setting.LastCookie);
            if (!string.IsNullOrEmpty(html))
            {
                string body = html;
                if (Setting.DetailInfo.BaseRule != null)
                {
                    body = TFilter(body, Setting.DetailInfo.BaseRule);
                }
                var rules = Setting.DetailInfo.Rules;
                foreach (var item in rules)
                {
                    result.Deta.Add(item.Key, TFilter(body, item.Value));
                }
                string imgList = html;
                if (Setting.DetailInfo.ImgRule != null)
                {
                    imgList = TFilter(imgList, Setting.DetailInfo.ImgRule);
                }
                var imgUrls = TFilters(imgList, Setting.DetailInfo.ImgRule);
                foreach (var item in imgUrls)
                {
                    if (!string.IsNullOrEmpty(item))
                    {
                        result.Files.Add(AttachRoot(item), string.Empty);
                    }
                }
                if (result.Files.Count > 0)
                {
                    foreach (var item in result.Files)
                    {
                        var workItem = new WorkItem<GatherInfo>();
                        workItem.Params.Add(item);
                        workItem.Type = WorkItemType.DownFile;
                        AddWorkItem(workItem);
                    }
                }
            }
            return result;
        }
        private void DownloadFile(string url, string filePath)
        {
            Url.DownloadFile(url, Setting.LastCookie, filePath);
        }

        #region Tools
        private string TFilter(string source, GatherRule rule)
        {
            string result = source;
            if (rule != null)
            {
                switch (rule.MatchType)
                {
                    case ZDT.Text.MatchType.Replace:
                        result = Text.StringMatch.Parse(source,rule.StartMark,rule.EndMark,rule.Profix,rule.ReplaceRule,rule.DescPlace);
                        break;
                    case ZDT.Text.MatchType.Match:
                        result = Text.StringMatch.Match(source,rule.Pattern);
                        break;
                    default:
                        break;
                }
            }
            return result;
        }
        private List<string> TFilters(string source, GatherRule rule)
        {
            List<string> result = new List<string>();
            if (rule != null)
            {
                switch (rule.MatchType)
                {
                    case ZDT.Text.MatchType.Replace:
                        string value = Text.StringMatch.Parse(source, rule.StartMark, rule.EndMark, rule.Profix, rule.ReplaceRule, rule.DescPlace);
                        result.Add(value);
                        break;
                    case ZDT.Text.MatchType.Match:
                        var v = new PatternSetting();
                        v.Source = source;
                        v.Pattern = rule.Pattern;
                        var t = Text.StringMatch.Match(v);
                        foreach (var item in t)
                        {
                            result.Add(item.Result);
                        }
                        break;
                    default:
                        break;
                }
            }
            return result;
        }
        private List<Dictionary<string,string>> TFilters(string source, GatherRule rule,List<string> keys)
        {
            var v = new PatternSetting();
            v.Source = source;
            v.Pattern = rule.Pattern;
            var result = StringMatch.Match(v, keys);
            return result;
        }

        public string AttachRoot(string url)
        {
            string result = url;
            if (!url.ToLower().StartsWith(StringMatch.HP))
            {
                result = Setting.RootUrl;
                if (!url.StartsWith("/"))
                {
                    result += "/";
                }
                result += url;
            }
            return result;
        }
        #endregion
    }
}
